﻿using AutoMapper;
using Developer.Core.Aggregation.Api.Dtos;
using Developer.Core.Aggregation.Api.Models.UserService;
using Developer.Core.Aggregation.Api.Pos.UserService;
using Developer.Core.Aggregation.Api.Services.UserService;
using Developer.Core.FrameWork.DynamicMiddlePlatformService.Service;
using Developer.Core.FrameWork.ElasticsearchHelp;
using Developer.Core.FrameWork.GlobalVar;
using Developer.Core.FrameWork.RedisExtensions.Service;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Developer.Core.Aggregation.Api.Controllers
{
    /// <summary>
    /// 用户控制器
    /// </summary>
    [Route("api/User")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private readonly IUserClient userClient;
        private readonly IDynamicMiddlePlatformUrl dynamicMiddlePlatformUrl; // 中台url
        private readonly HttpClient httpClient;
        private readonly IRedisBasketRepository _redisBasketRepository;
        private readonly IElasticsearchServer elasticsearchServer;

        public UserController(IUserClient userClient, IDynamicMiddlePlatformUrl dynamicMiddlePlatformUrl
                                , IHttpClientFactory httpClientFactory, IRedisBasketRepository redisBasketRepository,
            IElasticsearchServer elasticsearchServer)
        {
            this.userClient = userClient;
            this.dynamicMiddlePlatformUrl = dynamicMiddlePlatformUrl;
            this.httpClient = httpClientFactory.CreateClient();
            this._redisBasketRepository = redisBasketRepository;
            this.elasticsearchServer = elasticsearchServer;
        }

        public async Task Test()
        {
            var msg = $"这里是一条日志{DateTime.Now}";
            await _redisBasketRepository.ListLeftPushAsync(GlobalVars.RedisKey, msg);
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="userForm"></param>
        [HttpPost]
        public User Post([FromForm] UserPo userPo)
        {
            // 1、userForm 转换成领域模型
            var configuration = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<UserPo, User>();
            });

            IMapper mapper = configuration.CreateMapper();

            // 2、转换
            User user = mapper.Map<UserPo, User>(userPo);
            user.CreateTime = new DateTime();

            // 3、用户进行注册
            user = userClient.RegistryUsers(user);

            return user;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <returns></returns>
        [HttpGet("Login")]
        public async Task<UserDto> PostLogin([FromForm] LoginPo loginPo)
        {
            // 1、查询用户信息 
            // 2、判断用户信息是否存在
            // 3、将用户信息生成token进行存储
            // 4、将token信息存储到cookie或者session中
            // 5、返回成功信息和token
            // 6、对于token进行认证(也就是身份认证)

            // 1、获取IdentityServer接口文档
            var res = await this.elasticsearchServer.SearchAsync("canal", "_doc", @"
{
    ""from"": 0,
    ""size"": 10,
    ""query"": {
        ""bool"":{ 
             ""should"":[
               {""match"": { ""name"": ""tony"" }},
               {""match"": { ""age"": ""22"" }}
             ]
        }
    }
}");
            string IdentityServiceUrl = dynamicMiddlePlatformUrl.GetMiddlePlatformUrl("https", "IdentityService");
            DiscoveryDocumentResponse discoveryDocument = httpClient.GetDiscoveryDocumentAsync(IdentityServiceUrl).Result;
            if (discoveryDocument.IsError)
            {
                Console.WriteLine($"[DiscoveryDocumentResponse Error]: {discoveryDocument.Error}");
            }

            // 2、根据用户名和密码建立token
            TokenResponse tokenResponse = httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest()
            {
                Address = discoveryDocument.TokenEndpoint,
                ClientId = "client-password",
                ClientSecret = "secret",
                GrantType = "password",
                UserName = loginPo.UserName,
                Password = loginPo.Password
            }).Result;
            // 3、返回AccessToken
            if (tokenResponse.IsError)
            {
                throw new Exception(tokenResponse.Error + "," + tokenResponse.Raw);
            }

            // 4、获取用户信息
            UserInfoResponse userInfoResponse = httpClient.GetUserInfoAsync(new UserInfoRequest()
            {
                Address = discoveryDocument.UserInfoEndpoint,
                Token = tokenResponse.AccessToken
            }).Result;

            // 5、返回UserDto信息
            UserDto userDto = new UserDto();
            userDto.UserId = userInfoResponse.Json.TryGetString("sub");
            userDto.UserName = loginPo.UserName;
            userDto.AccessToken = tokenResponse.AccessToken;
            userDto.ExpiresIn = tokenResponse.ExpiresIn;

            // 1、加密方式有很多，证书加密，数据安全的

            // 1、cookie存储
            // 2、本地缓存

            string access_token = await GetAccessToken();

            //2、使用AccessToken 进行资源访问
            string result = await UseAccessToken(tokenResponse.AccessToken);

            return null;
        }

        [HttpGet]
        [Authorize]
        public User Get([FromForm] int id)
        {
            var user = userClient.GetUser(id);
            return user;
        }


        public static async Task<string> GetAccessToken()
        {
            //1、建立连接
            HttpClient client = new HttpClient();
            DiscoveryDocumentResponse disco = await client.GetDiscoveryDocumentAsync("https://localhost:5003");
            if (disco.IsError)
            {
                Console.WriteLine($"[DiscoveryDocumentResponse Error]: {disco.Error}");
            }
            // 1.1、通过客户端获取AccessToken
            TokenResponse tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = disco.TokenEndpoint, // 1、生成AccessToken中心
                ClientId = "client", // 2、客户端编号
                ClientSecret = "secret",// 3、客户端密码
                Scope = "UserService" // 4、客户端需要访问的API
            });

            if (tokenResponse.IsError)
            {
                string errorDesc = tokenResponse.ErrorDescription;
                if (string.IsNullOrEmpty(errorDesc)) errorDesc = "";
                if (errorDesc.Equals("invalid_username_or_password"))
                {
                    Console.WriteLine("用户名或密码错误，请重新输入！");
                }
                else
                {
                    Console.WriteLine($"[TokenResponse Error]: {tokenResponse.Error}, [TokenResponse Error Description]: {errorDesc}");
                }
            }
            else
            {
                Console.WriteLine($"Access Token: {tokenResponse.Json}");
                Console.WriteLine($"Access Token: {tokenResponse.RefreshToken}");
                Console.WriteLine($"Access Token: {tokenResponse.ExpiresIn}");
            }
            return tokenResponse.AccessToken;
        }

        /// <summary>
        /// 2、使用token
        /// </summary>
        public static async Task<string> UseAccessToken(string AccessToken)
        {
            HttpClient apiClient = new HttpClient();
            apiClient.SetBearerToken(AccessToken); // 1、设置token到请求头
            HttpResponseMessage response = await apiClient.GetAsync("http://localhost:5002/Users/5");
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine($"API Request Error, StatusCode is : {response.StatusCode}");
            }
            else
            {
                string content = await response.Content.ReadAsStringAsync();
                Console.WriteLine("");
                Console.WriteLine($"Result: {JArray.Parse(content)}");

                // 3、输出结果到页面
                return JArray.Parse(content).ToString();
            }
            return "";

        }
    }
}
